//------------------------------------------------------------------------
// Abstract: Implement of Format
//
// Authoring: XiaoHanxiong
//
// Time: 2014.03.21
//
// Static test:
//
// Version history:
//		Ver_1.0	: 2014.03.21	XiaoHanxiong
//------------------------------------------------------------------------
#include "stdafx.h"
#include "Format.h"


namespace Library
{

	Format::Format()
	{

	}

	Format::~Format()
	{

	}
		
	/*
		Basic operation on string that consist of alphabet or number
		IsLetter:	is a alphabet
		IsNumber:	is a number
		Lower:		lower a case
		Upper:		upper a case
	*/
	bool Format::IsLetterA( const string& str )
	{
		for(string::size_type n = 0; n < str.size(); n++)
		{
			if( ('a' <= str[n] && str[n] <= 'z') || 
				('A' <= str[n] && str[n] <= 'Z') )
				;
			else return false;
		}

		return true;
	}

	bool Format::IsLetterA( const char& ch )
	{
		if( ('a' <= ch && ch <= 'z') || 
			('A' <= ch && ch <= 'Z') )
			return true;
		else return false;
	}

	bool Format::IsNumberA( const string& str )
	{
		for(string::size_type n = 0; n < str.size(); n++)
		{
			if( '0' <= str[n] && str[n] <= '9' )
				return true;
			else return false;
		}

		return true;
	}

	bool Format::IsNumberA( const char& ch )
	{
		if( '0' <= ch && ch <= '9' )
			return true;
		else return false;
	}

	void Format::LowerA( string& str )
	{
		for(string::size_type n = 0; n < str.size(); n++)
		{
			if( 'a' <= str[n] && str[n] <= 'a' )
				str[n] += 32;
		}
	}

	void Format::LowerA( char& ch )
	{
		if( 'A' <= ch && ch <= 'Z' )
			ch += 32;
	}

	void Format::UpperA( string& str )
	{
		for(string::size_type n = 0; n < str.size(); n++)
		{
			if( 'a' <= str[n] && str[n] <= 'z' )
				str[n] -= 32;
		}
	}

	void Format::UpperA( char& ch )
	{
		if( 'a' <= ch && ch <= 'z' )
			ch -= 32;
	}

	/*
		Function: NumToStringTA
		Abstract: Convert a number to string
		_Num _num[in]:		input number
		string& str[out]:	output string
	*/
	template<typename _Num>
	void _tplNumToDecStringA(_Num _num, string& str)
	{
		std::stringstream sbuffer;
		sbuffer << _num;
		str = sbuffer.str();
	}

	void Format::NumToDecStringA( short in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( unsigned short in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( int in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( unsigned int in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( long in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( unsigned long in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( __int64 in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( unsigned __int64 in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( float in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}

	void Format::NumToDecStringA( double in, string& str )
	{
		_tplNumToDecStringA(in, str);
	}


	/*
		Function: StringToNumTA
		Abstract: Convert a string to number
		string& str[in]:	input string
		_Num _num[out]:		output number
	*/
	template<typename _Num>
	void _tplDecStringToNumA(string& str, _Num& _num)
	{
		std::stringstream sbuffer;
		sbuffer.str(str);
		if(sbuffer >> _num) ;
		else _num = 0;
	}

	void Format::DecStringToNumA( string& str, short& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, unsigned short& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, int& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, unsigned int& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, long& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, unsigned long& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, __int64& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, unsigned __int64& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, float& out )
	{
		_tplDecStringToNumA(str, out);
	}

	void Format::DecStringToNumA( string& str, double& out )
	{
		_tplDecStringToNumA(str, out);
	}

	/*
		Function: NumToHexStringTA
		Abstract: Convert a number to hex string
		_Num _num[in]:		input number
		const char*[in]:	output format
		string& str[out]:	output hex string
	*/
	template<typename _Num>
	void _tplNumToHexStringA(_Num _num, const char* format, string& str )
	{
		char hex_buffer[32] = {0};
		sprintf_s(hex_buffer, 32, format, _num);
		str = hex_buffer;
	}

	void Format::NumToHexStringA( short in, string& str )
	{
		_tplNumToHexStringA((unsigned short)in, "%x", str);
	}

	void Format::NumToHexStringA( unsigned short in, string& str )
	{
		_tplNumToHexStringA(in, "%x", str);
	}

	void Format::NumToHexStringA( int in, string& str )
	{
		_tplNumToHexStringA((unsigned int)in, "%x", str);
	}

	void Format::NumToHexStringA( unsigned int in, string& str )
	{
		_tplNumToHexStringA(in, "%x", str);
	}

	void Format::NumToHexStringA( long in, string& str )
	{
		_tplNumToHexStringA((unsigned long)in, "%x", str);
	}

	void Format::NumToHexStringA( unsigned long in, string& str )
	{
		_tplNumToHexStringA(in, "%x", str);
	}

	void Format::NumToHexStringA( __int64 in, string& str )
	{
		_tplNumToHexStringA(in, "%I64x", str);

	}

	void Format::NumToHexStringA( unsigned __int64 in, string& str )
	{
		_tplNumToHexStringA((unsigned __int64)in, "%I64x", str);
	}


	/*
		Function: HexStringToNumTA
		Abstract: Convert a number to bit string
		_Num _num[in]:		output number
		string& str[out]:	input octal number string
	*/
	template<typename _Num>
	void _tplHexStringToNumA( string& str, _Num& _num )
	{
		string::reverse_iterator itr = str.rbegin();
		string::size_type multi = 0;
		_Num tmp_num = 0;

		_num = 0;
		for( ; itr != str.rend(); itr++, multi+=4 )
		{
			if(*itr >= '0' && *itr <= '9')  tmp_num |= (_Num)(*itr - '0') << multi;
			else if(*itr >= 'a' && *itr <= 'f') tmp_num |= (_Num)(*itr - 'a' + 10) << multi;
			else if(*itr >= 'A' && *itr <= 'F') tmp_num |= (_Num)(*itr - 'A' + 10) << multi;
			else return;
		}
		_num = tmp_num;
	}

	void Format::HexStringToNumA( string& str, short& out )
	{
		_tplHexStringToNumA(str, out);
	}

	void Format::HexStringToNumA( string& str, unsigned short& out )
	{
		_tplHexStringToNumA(str, out);
	}

	void Format::HexStringToNumA( string& str, int& out )
	{
		_tplHexStringToNumA(str, out);
	}

	void Format::HexStringToNumA( string& str, unsigned int& out )
	{
		_tplHexStringToNumA(str, out);
	}

	void Format::HexStringToNumA( string& str, long& out )
	{
		_tplHexStringToNumA(str, out);
	}

	void Format::HexStringToNumA( string& str, unsigned long& out )
	{
		_tplHexStringToNumA(str, out);
	}

	void Format::HexStringToNumA( string& str, __int64 & out )
	{
		_tplHexStringToNumA(str, out);
	}

	void Format::HexStringToNumA( string& str, unsigned __int64& out )
	{
		_tplHexStringToNumA(str, out);
	}

	/*
		Function: NumToBitStringTA
		Abstract: Convert binary string to number
		_Num _num[in]:		input number
		string& str[out]:	output bit string
	*/
	template<typename _Num>
	void _tplBinStringToNumA( string& str, _Num& _num )
	{
		string::reverse_iterator itr = str.rbegin();
		string::size_type multi = 0;
		_Num tmp_num = 0;
		
		_num = 0;
		for( ; itr != str.rend(); itr++, multi++ )
		{
			if(*itr == '0') ;
			else if(*itr == '1') tmp_num |= (_Num)(0x1 << multi);
			else return;
		}
		_num = tmp_num;
	}

	void Format::BinStringToNumA( string& str, short& out )
	{
		_tplBinStringToNumA(str, out);
	}

	void Format::BinStringToNumA( string& str, unsigned short& out )
	{
		_tplBinStringToNumA(str, out);
	}

	void Format::BinStringToNumA( string& str, int& out )
	{
		_tplBinStringToNumA(str, out);
	}

	void Format::BinStringToNumA( string& str, unsigned int& out )
	{
		_tplBinStringToNumA(str, out);
	}

	void Format::BinStringToNumA( string& str, long& out )
	{
		_tplBinStringToNumA(str, out);
	}

	void Format::BinStringToNumA( string& str, unsigned long& out )
	{
		_tplBinStringToNumA(str, out);
	}

	void Format::BinStringToNumA( string& str, __int64& out )
	{
		_tplBinStringToNumA(str, out);
	}

	void Format::BinStringToNumA( string& str, unsigned __int64& out )
	{
		_tplBinStringToNumA(str, out);
	}


	/*
		Function: NumToBitStringTA
		Abstract: Convert number to binary string
		_Num _num[in]:		input number
		string& str[out]:	output bit string
	*/
	template<typename _Num>
	void _tplNumToBinStringA(_Num _num, string& str)
	{
		_Num remain = 0;
		str.clear();

		if(_num != 0)
		{
			while(_num != 0)
			{
				remain = _num % 2;
				if(remain) str.insert(str.begin(), '1');
				else str.insert(str.begin(), '0');
				_num /= 2;
			}
		}
		else str.push_back('0');
	}

	void Format::NumToBinStringA( short in, string& str )
	{
		_tplNumToBinStringA((unsigned short)in, str);
	}

	void Format::NumToBinStringA( unsigned short in, string& str )
	{
		_tplNumToBinStringA(in, str);
	}

	void Format::NumToBinStringA( int in, string& str )
	{
		_tplNumToBinStringA((unsigned int)in, str);
	}

	void Format::NumToBinStringA( unsigned int in, string& str )
	{
		_tplNumToBinStringA(in, str);
	}

	void Format::NumToBinStringA( __int64 in, string& str )
	{
		_tplNumToBinStringA((unsigned __int64)in, str);
	}

	void Format::NumToBinStringA( unsigned __int64 in, string& str )
	{
		_tplNumToBinStringA(in, str);
	}

	
	/*
		Function: _tplNumToOctStringA
		Abstract: Convert a number to octal string
		_Num _num[in]:		input number
		const char*[in]:	output format
		string& str[out]:	output octal string
	*/
	template<typename _Num>
	void _tplNumToOctStringA(_Num _num, const char* format, string& str )
	{
		char hex_buffer[32] = {0};
		sprintf_s(hex_buffer, 32, format, _num);
		str = hex_buffer;
	}

	void Format::NumToOctStringA( short in, string& str )
	{
		_tplNumToOctStringA((unsigned short)in, "%o", str);
	}

	void Format::NumToOctStringA( unsigned short in, string& str )
	{
		_tplNumToOctStringA(in, "%o", str);
	}

	void Format::NumToOctStringA( int in, string& str )
	{
		_tplNumToOctStringA((unsigned int)in, "%o", str);
	}

	void Format::NumToOctStringA( unsigned int in, string& str )
	{
		_tplNumToOctStringA(in, "%o", str);
	}

	void Format::NumToOctStringA( long in, string& str )
	{
		_tplNumToOctStringA((unsigned long)in, "%o", str);
	}

	void Format::NumToOctStringA( unsigned long in, string& str )
	{
		_tplNumToOctStringA(in, "%o", str);
	}

	void Format::NumToOctStringA( __int64 in, string& str )
	{
		_tplNumToOctStringA((unsigned __int64)in, "%I64o", str);
	}

	void Format::NumToOctStringA( unsigned __int64 in, string& str )
	{
		_tplNumToOctStringA(in, "%I64o", str);
	}


	/*
		Function: _tplNumToOctStringA
		Abstract: Convert a number to octal string
		_Num _num[out]:		output number
		const char*[in]:	output format
		string& str[in]:	input octal string
	*/
	template<typename _Num>
	void _tplOctStringToNumA(_Num& _num, const char* format, string& str )
	{
		sscanf_s(str.c_str(), format, &_num);
	}

	void Format::OctStringToNumA( string& str, short& out )
	{
		_tplOctStringToNumA(out, "%o", str);
	}

	void Format::OctStringToNumA( string& str, unsigned short& out )
	{
		_tplOctStringToNumA(out, "%o", str);
	}

	void Format::OctStringToNumA( string& str, int& out )
	{
		_tplOctStringToNumA(out, "%o", str);
	}

	void Format::OctStringToNumA( string& str, unsigned int& out )
	{
		_tplOctStringToNumA(out, "%o", str);
	}

	void Format::OctStringToNumA( string& str, long& out )
	{
		_tplOctStringToNumA(out, "%o", str);
	}

	void Format::OctStringToNumA( string& str, unsigned long& out )
	{
		_tplOctStringToNumA(out, "%o", str);
	}

	void Format::OctStringToNumA( string& str, __int64& out )
	{
		_tplOctStringToNumA(out, "%I64o", str);
	}

	void Format::OctStringToNumA( string& str, unsigned __int64& out )
	{
		_tplOctStringToNumA(out, "%I64o", str);
	}
}// _Library
